--[[
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Detection for CVE-2015-2426
This lua script can be run standalone and verbosely on an OTF
echo "run()" | luajit -i <script name> <otf file>
Darien Huss
--]]

local struct = require 'struct'

function init (args)
    local needs = {}
    needs["http.response_body"] = tostring(true)
    return needs
end

function otf_handler(t,verbose)
    local lW3Qtm = 0
    local m3Kh4A4p,endpos = string.find(string.sub(t,1,512),"GPOS",8,true)
    if m3Kh4A4p then
        if (verbose==1) then print("Checking for exploit...") end
        local XBQl1ZKlz3WML = struct.unpack(">I4",string.sub(t,m3Kh4A4p+8,m3Kh4A4p+12))
        local JWPNj9vwtEJd = struct.unpack(">I4",string.sub(t,m3Kh4A4p+12,m3Kh4A4p+16))
        local c42Z5feS8Aor = string.sub(t,XBQl1ZKlz3WML+1,XBQl1ZKlz3WML+JWPNj9vwtEJd)
        local OMxfqj = struct.unpack(">I2",string.sub(c42Z5feS8Aor,9,10))+1
        local QQccb57IymQt = struct.unpack(">I2",string.sub(c42Z5feS8Aor,OMxfqj,OMxfqj+1))
        local ZyYotB2iiDoO6 = 1
        while ZyYotB2iiDoO6 <= QQccb57IymQt do
            local M9TVRXZ4evo = (ZyYotB2iiDoO6*2)+OMxfqj
            local k37vOs3gCkod = struct.unpack(">I2",string.sub(c42Z5feS8Aor,M9TVRXZ4evo,M9TVRXZ4evo+1))+OMxfqj
            local S3zBIF4IaXj = struct.unpack(">I2",string.sub(c42Z5feS8Aor,k37vOs3gCkod,k37vOs3gCkod+1))
            if S3zBIF4IaXj == 2 then
                local SAPn14ROAXSjH = struct.unpack(">I2",string.sub(c42Z5feS8Aor,k37vOs3gCkod+4,k37vOs3gCkod+5))
                local mnk4bl9w5 = 1
                while mnk4bl9w5 <= SAPn14ROAXSjH do
                    local TLAxob22Vbkpx = (mnk4bl9w5*2)+k37vOs3gCkod+4
                    local tUKUTX = struct.unpack(">I2",string.sub(c42Z5feS8Aor,TLAxob22Vbkpx,TLAxob22Vbkpx+1))+k37vOs3gCkod
                    local DiWQxNh94SS = struct.unpack(">I2",string.sub(c42Z5feS8Aor,tUKUTX,tUKUTX+1))
                    if DiWQxNh94SS == 2 then
                        if struct.unpack(">I2",string.sub(c42Z5feS8Aor,tUKUTX+12,tUKUTX+13)) == 0 or
                            struct.unpack(">I2",string.sub(c42Z5feS8Aor,tUKUTX+14,tUKUTX+15)) == 0 then
                            lW3Qtm = 1
                            if (verbose==1) then print("Found exploit...") end
                        end
                    end
                    mnk4bl9w5 = mnk4bl9w5 + 1
                end
            end
            ZyYotB2iiDoO6 = ZyYotB2iiDoO6 + 1
        end
    end
    return lW3Qtm
end

function common(t,o,verbose)
    rtn = 0
    rtn = otf_handler(t,verbose)
    return rtn
end

function match(args)
    local t = tostring(args["http.response_body"])
    local o = args["offset"]
    return common(t,o,0)
end

function run()
  local f = io.open(arg[1])
  local t = f:read("*all")
  f:close()
  common(t,4,1)
end